package vn.edu.ptithcm.pim.dao;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.LockMode;
import org.hibernate.Transaction;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import vn.edu.ptithcm.pim.constant.Functions;
import vn.edu.ptithcm.pim.dom.EmployeeFunctionInProject;
import vn.edu.ptithcm.pim.dom.EmployeeFunctionInProjectId;

@SuppressWarnings({ "rawtypes" })
public class EmployeeFunctionInProjectDao extends HibernateDaoSupport {

	public void save(EmployeeFunctionInProject employeeFunctionInProject) {
		try {
			Transaction tx = getSession().beginTransaction();
			getHibernateTemplate().save(employeeFunctionInProject);
			tx.commit();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public void saveOrUpdate(EmployeeFunctionInProject employeeFunctionInProject) {
		try {
			Transaction tx = getSession().beginTransaction();
			getHibernateTemplate().update(employeeFunctionInProject);
			tx.commit();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public void lock(EmployeeFunctionInProject employeeFunctionInProject) {
		try {
			Transaction tx = getSession().beginTransaction();
			getHibernateTemplate().lock(employeeFunctionInProject,
					LockMode.NONE);
			tx.commit();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public void delete(EmployeeFunctionInProject employeeFunctionInProject) {
		try {
			Transaction tx = getSession().beginTransaction();
			getHibernateTemplate().delete(employeeFunctionInProject);
			tx.commit();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public void removeEmployeeOutOfProject(Long projectId, Long employeeId) {
		try {
			Transaction tx = getSession().beginTransaction();
			StringBuilder sql = new StringBuilder();
			sql.append(
					"delete EmployeeFunctionInProject as efip where efip.project.projectid ='")
					.append(projectId)
					.append("' and efip.employee.employeeid='")
					.append(employeeId).append("'");
			getHibernateTemplate().bulkUpdate(sql.toString());
			tx.commit();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public EmployeeFunctionInProject merge(
			EmployeeFunctionInProject employeeFunctionInProject) {
		try {
			return (EmployeeFunctionInProject) getHibernateTemplate().merge(
					employeeFunctionInProject);
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public EmployeeFunctionInProject findById(EmployeeFunctionInProjectId id) {
		try {
			return (EmployeeFunctionInProject) getHibernateTemplate().get(
					EmployeeFunctionInProject.class, id);
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List findByExample(
			EmployeeFunctionInProject EmployeeFunctionInProject) {
		try {
			return getHibernateTemplate().findByExample(
					"EmployeeFunctionInProject", EmployeeFunctionInProject);
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List getAll() {
		try {
			return getHibernateTemplate().loadAll(
					EmployeeFunctionInProject.class);
		} catch (RuntimeException re) {
			throw re;
		}
	}

	@SuppressWarnings("unchecked")
	public List getBySearchKey(Long projectId, Long rankId, Long diplomaId,
			String language, String searchKey) {
		try {
			List efips = new ArrayList(0);
			if ("Keyword...".equals(searchKey)) {
				searchKey = "";
			}
			if (searchKey.isEmpty() && language.isEmpty()
					&& rankId.intValue() == 0 && diplomaId.intValue() == 0) {
				efips.addAll(findByProjectId(projectId));
			} else {
				Criteria c = getSession().createCriteria(
						EmployeeFunctionInProject.class);
				c.createAlias("project", "project");
				c.add(Restrictions.eq("project.projectid", projectId));
				c.createAlias("employee", "employee");

				if (rankId.intValue() != 0) {
					c.createAlias("employee.rank", "rank");
					c.add(Restrictions.eq("rank.rankid", rankId));
				}
				if (diplomaId.intValue() != 0) {
					c.createAlias("employee.diploma", "diploma");
					c.add(Restrictions.eq("diploma.diplomaid", diplomaId));
				}
				if (!language.isEmpty()) {
					c.add(Restrictions.ilike("employee.languages", "%"
							+ language + "%"));
				}
				if (!searchKey.isEmpty()) {
					Criterion visa = Restrictions.ilike("employee.visa", "%"
							+ searchKey + "%");
					Criterion firstname = Restrictions.ilike(
							"employee.firstname", "%" + searchKey + "%");
					Criterion lastname = Restrictions.ilike(
							"employee.lastname", "%" + searchKey + "%");

					Disjunction disjunction = Restrictions.disjunction();
					disjunction.add(visa);
					disjunction.add(firstname);
					disjunction.add(lastname);
					c.add(disjunction);
				}
				c.addOrder(Order.asc("employee.firstname"));
				efips.addAll(c.list());
			}
			return efips;
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List findByProjectId(Long projectId) {
		try {
			Criteria c = getSession().createCriteria(
					EmployeeFunctionInProject.class);
			c.createAlias("project", "project");
			c.add(Restrictions.eq("project.projectid", projectId));
			c.createAlias("employee", "employee");
			c.addOrder(Order.asc("employee.firstname"));
			return c.list();
		} catch (RuntimeException re) {
			throw re;
		}
	}

	public EmployeeFunctionInProject getGroupLeaderFunction(Long projectId) {
		try {
			Criteria c = getSession().createCriteria(
					EmployeeFunctionInProject.class);
			c.createAlias("project", "project");
			c.add(Restrictions.eq("project.projectid", projectId));
			c.createAlias("function", "function");
			c.add(Restrictions
					.eq("function.functionid", new Long(Functions.GL)));

			return c.list().size() == 1 ? (EmployeeFunctionInProject) c.list()
					.get(0) : null;

		} catch (RuntimeException re) {
			throw re;
		}
	}

	public List getProjectsByVisa(String visa) {
		try {
			StringBuilder sql = new StringBuilder();
			sql.append(
					"select distinct efip.project from EmployeeFunctionInProject as efip ")
					.append("where efip.project.projectStatus.statusid != 4 and efip.employee.visa ='")
					.append(visa).append("' order by efip.project.name");
			return getHibernateTemplate().find(sql.toString());
		} catch (RuntimeException re) {
			throw re;
		}
	}
}
